package com.yuan.service;


import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnsCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.UUID;

/**
 * @author yuandong
 * @company KB
 * @create 2022-03-27 11:03
 */
@Component
@Slf4j
public class RabbitService implements ConfirmCallback , ReturnsCallback{

	@Autowired
	private RabbitTemplate rabbitTemplate;


	/**
	 * 发送mq消息 工作队列模式
	 * @param routingKey
	 * @param object
	 * @throws InterruptedException
	 */
	public void sendWorkQueue(String routingKey, Object object){
		//这是设置回调能收到的发送到响应
		rabbitTemplate.setConfirmCallback(this);
		//如果设置备份队列，则不起作用
		rabbitTemplate.setMandatory(true);
		rabbitTemplate.setReturnsCallback(this);
		String messageId = UUID.randomUUID().toString();
		CorrelationData correlationData = new CorrelationData(messageId);
		rabbitTemplate.convertAndSend(routingKey, object, correlationData);
	}

	/**
	 * 发送mq消息 广播模式
	 * @param exchange
	 * @param object
	 */
	public void sendFanout(String exchange, Object object){
		//这是设置回调能收到的发送到响应
		rabbitTemplate.setConfirmCallback(this);
		//如果设置备份队列，则不起作用
		rabbitTemplate.setMandatory(true);
		rabbitTemplate.setReturnsCallback(this);
		String messageId = UUID.randomUUID().toString();
		CorrelationData correlationData = new CorrelationData(messageId);
		rabbitTemplate.convertAndSend(exchange, "", object, correlationData);
	}


	/**
	 * 发送mq消息 路由模式
	 * @param exchange
	 * @param routingKey 路由key
	 * @param object
	 */
	public void sendDirect(String exchange, String routingKey, Object object){
		//这是设置回调能收到的发送到响应
		rabbitTemplate.setConfirmCallback(this);
		//如果设置备份队列，则不起作用
		rabbitTemplate.setMandatory(true);
		rabbitTemplate.setReturnsCallback(this);
		String messageId = UUID.randomUUID().toString();
		CorrelationData correlationData = new CorrelationData(messageId);
		rabbitTemplate.convertAndSend(exchange, routingKey, object, correlationData);
	}

	/**
	 * 消息确认回调
	 * 消息进入交换机错误，会触发该回调
	 * @param correlationData
	 * @param ack
	 * @param cause
	 */
	@Override
	public void confirm(CorrelationData correlationData, boolean ack, String cause) {
		if(!ack){
			log.info("消息发送到交换机失败:correlationData({}),ack({}),cause({})",correlationData,ack,cause);
		}
	}


	/**
	 * 消息确认回调
	 *  消息从交换机到队列错误，会触发该回调
	 * @param returnedMessage
	 */
	@Override
	public void returnedMessage(ReturnedMessage returnedMessage) {
		log.info("消息从交换机投递到队列时丢失:exchange({}),route({}),replyCode({}),replyText({}),message:{}",returnedMessage.getExchange(),returnedMessage.getRoutingKey(),returnedMessage.getReplyCode(),returnedMessage.getReplyText(),returnedMessage.getMessage());

	}

}
